package manage.sys.service.impl;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import org.apache.commons.collections.CollectionUtils;
import org.springframework.cache.annotation.CacheEvict;
import org.springframework.cache.annotation.Cacheable;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import luxing.common.service.impl.CommonServiceImpl;
import luxing.util.ResourceUtil;
import manage.sys.entity.Menu;
import manage.sys.service.MenuService;

/**
 * 
 * @author zzc
 *
 */
@Service("menuService")
@Transactional
public class MenuServiceImpl extends CommonServiceImpl implements MenuService {

	public void initMenu() {
		List<Menu> menuList = listAll(Menu.class);
		for (Menu menu : menuList) {
			ResourceUtil.menuMap.put(menu.getUrl(), menu);
		}
	}

	@Cacheable(value = "menuCache", key = "#url")
	public Menu getByUrl(String url) {
		String hql = "select m from Menu m where m.url=?";
		return getUniqueByHql(hql, url);
	}

	@CacheEvict(value = "menuCache", key = "#menu.url", beforeInvocation = true)
	public void updateMenu(Menu menu) {
		saveOrUpdate(menu);
		updateChildMenuLevel(menu);
	}

	private void updateChildMenuLevel(Menu menu) {
		if (CollectionUtils.isNotEmpty(menu.getChildMenus())) {
			for (Menu childMenu : menu.getChildMenus()) {
				childMenu.setLevel(menu.getLevel() + 1);
				saveOrUpdate(childMenu);
				updateChildMenuLevel(childMenu);
			}
		}
	}

	@CacheEvict(value = "menuCache", key = "#menu.url", beforeInvocation = true)
	public void deleteMenu(Menu menu) {
		delete(menu);
	}

	public List<Menu> listByType(String type) {
		String hql = "from Menu where type=?";
		return listByHql(hql, type);
	}

	public List<Menu> listByUser(String userId) {
		String hql = "select m from Menu m,User u where m in elements(u.menuList) and u.id=?";
		return listByHql(hql, userId);
	}

	public List<Menu> listByManageUser(String userId) {
		String hql = "select m from Menu m,ManageUser mu where m in elements(mu.menuList) and mu.id=?";
		return listByHql(hql, userId);
	}

	public List<String> listMenuIdsByUser(String userId) {
		String hql = "select m.id from Menu m,User u where m in elements(u.menuList) and u.id=?";
		List<String> idList = listByHql(hql, userId);
		return idList;
	}

	public List<String> listMenuIdsByManageUser(String userId) {
		String hql = "select m.id from Menu m,ManageUser mu where m in elements(mu.menuList) and mu.id=?";
		List<String> idList = listByHql(hql, userId);
		return idList;
	}

	@Cacheable(value = "menuCache", key = "#userId.concat(#url)")
	public Menu getByUserAndUrl(String userId, String url) {
		String hql = "select m from Menu m,User u where m in elements(u.menuList) and u.id=? and m.url=?";
		return getUniqueByHql(hql, userId, url);
	}

	@Cacheable(value = "menuCache", key = "#userId.concat(#url)")
	public Menu getByManageUserAndUrl(String userId, String url) {
		String hql = "select m from Menu m,ManageUser mu where m in elements(mu.menuList) and mu.id=? and m.url=?";
		return getUniqueByHql(hql, userId, url);
	}

	public Map<Integer, List<Menu>> mapLevelMenuByUser(String userId) {
		Map<Integer, List<Menu>> resultMap = new HashMap<Integer, List<Menu>>();
		String hql = "select m from Menu m,User u where m in elements(u.menuList) and u.id=? order by m.order asc";
		List<Menu> menuList = listByHql(hql, userId);
		for (Menu menu : menuList) {
			if (resultMap.get(menu.getLevel().intValue()) == null) {
				List<Menu> list = new ArrayList<Menu>();
				list.add(menu);
				resultMap.put(menu.getLevel().intValue(), list);
			} else {
				resultMap.get(menu.getLevel().intValue()).add(menu);
			}
		}
		return resultMap;
	}

	public Map<Integer, List<Menu>> mapLevelMenuByManageUser(String userId) {
		Map<Integer, List<Menu>> resultMap = new HashMap<Integer, List<Menu>>();
		String hql = "select m from Menu m,ManageUser mu where m in elements(mu.menuList) and mu.id=? order by m.order asc";
		List<Menu> menuList = listByHql(hql, userId);
		for (Menu menu : menuList) {
			if (resultMap.get(menu.getLevel().intValue()) == null) {
				List<Menu> list = new ArrayList<Menu>();
				list.add(menu);
				resultMap.put(menu.getLevel().intValue(), list);
			} else {
				resultMap.get(menu.getLevel().intValue()).add(menu);
			}
		}
		return resultMap;
	}

}
